package com.gitee.wsl.ext.array

import kotlin.math.ln

/**
 * Calculates the entropy factor of a byte array.
 *
 *
 * This implementation will not create a copy of the internal array and will only internally initialize
 * an int array with 256 elements as temporary buffer.
 *
 *
 *
 * **Analysis**
 *
 *  * Time Complexity: `O(n)`
 *  * Space Complexity: `O(1)`
 *  * Alters Parameters: `false`
 *
 *
 *
 * @param array to calculate the entropy from
 * @return entropy factor, higher means higher entropy
 */
fun ByteArray.entropy(): Double {
    val buffer = IntArray(256){-1}

    for (element in this) {
        val unsigned = 0xff and element.toInt()
        if (buffer[unsigned] == -1) {
            buffer[unsigned] = 0
        }
        buffer[unsigned]++
    }

    var entropy = 0.0
    for (count in buffer) {
        if (count == -1) continue
        val prob = count.toDouble() / size
        entropy -= prob * (ln(prob) / ln(2.0))
    }
    return entropy
}